package com.shuyun.classloader.jar;

import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @description:
 *  https://www.cnblogs.com/lichmama/p/12858517.html
 *  使用hutool提供的JarClassLoader也能实现
 *
 * @author: shuai.chen@shuyun.com
 * @date: 2021/8/23 2:50 下午
 */
public class JarURLClassLoader {

    private URL jarURL;

    private URLClassLoader urlClassLoader;

    public JarURLClassLoader(URL jarURL) {
        this.jarURL = jarURL;
        urlClassLoader = new URLClassLoader(new URL[] { jarURL });
    }

    /**
     * 在指定包路径下加载子类
     *
     * @param basePackage 包
     * @param superClass 子类
     * @return
     */
    public Set<Class> loadClass(String basePackage, Class<?> superClass) throws Exception {
        JarFile jarFile = ((JarURLConnection) jarURL.openConnection()).getJarFile();

        Set<Class> classSet = new HashSet<>();
        // com/shuyun/open/protocol
        String pkgPath = basePackage.replace(".", "/");
        Enumeration<JarEntry> entries = jarFile.entries();
        Class<?> clazz;
        while (entries.hasMoreElements()) {
            JarEntry jarEntry = entries.nextElement();
            String entryName = jarEntry.getName();
            if (entryName.charAt(0) == '/') {
                entryName = entryName.substring(1);
            }
            if (jarEntry.isDirectory() || !entryName.startsWith(pkgPath) || !entryName.endsWith(".class")) {
                continue;
            }
            // com/shuyun/open/protocol/TaoProtocol.class  去掉  .class 后缀
            String className = entryName.substring(0, entryName.length() - 6);
            // 底层还是双亲委派
            // todo

            clazz = urlClassLoader.loadClass(className.replace("/", "."));
            if (clazz != null && !clazz.isInterface() && superClass.isAssignableFrom(clazz)) {
                classSet.add(clazz);
            }
        }
        return classSet;
    }

    public Class<?> loadClass(String name) {
        try {
            return urlClassLoader.loadClass(name);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public Class<?> findClass(String name) {
        return null;
    }

}
